/*
  configuration - type object that contains the following fields:
  
      data           - object containing local data to be used for the chart (this OR 'url' to be supplied)
      url            - url from which data will be fetched for the chart (this OR 'data' to be supplied)
    title          - id of an HTML element to present the title
    chart          - id of an HTML element to present the chart
    legend         - id of an HTML element to present the chart legend
    grid           - id of an HTML element to present the data grid
    footer         - id of an HTML element to present the footer
    type           - type of chart to display, one of: clusteredbars, areas, stackedcolumns, stackedbars, stackedareas, lines, hybrid, hybrid2, hybrid3
    refresh        - time interval in ms after which the data should be regularly refreshed
    fillColors     - an array of colors to use to fill successive chart elements
    labelmod       - the modulo of which independent labels to include on the axis
    legendvertical - true to display the legend in vertical layout
    series         - an array of objects, one for each series in the data, each containing the following fields:
                        name: a name for the series, used in the legend and grid headings, overriding the name for this series in the data
                        line: true if the series should use a line in a hybrid/hybrid2 chart, overriding the line option for this series in the data
                        chart: true if the series should be included in the chart (default: true)
                        grid: true if the series should be included in the data grid (default: true)
                        formatter: a formatter to use for this series in the data grid
                        styles: style for grid cells
                      (all fields are optional)
    range          - object containing the following fields:
                          name: a name for the range, used in the grid column heading
                          formatter: a formatter to use in the data grid
                          styles: style for grid column heading
                        (all fields are optional)
      reverse        - true to reverse the independent axis items in the chart. Default is false.
      colorAdjust    - true specifically for CI 105 and metrics comparison charts in order to
                       display the colours correctly
    
    (exactly one of 'data' and 'url' must be included; all other fields are optional)
            
  example - var foo = new uxd_chart({data:local.json, title:"tdiv", legend:"ldiv", footer:"fdiv", fillColors:["#6699cc","#99cc33","#aa0000"]}
*/
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.DnD");
dojo.require("dojox.grid.enhanced.plugins.Menu");
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
dojo.require("dojox.widget.PlaceholderMenuItem");

//Global object on which to hang functions. The SMD convention is to use 'smd' as the
//top level object onto which we tag functions etc.
if (window.demo === undefined) {
    var demo = {};
}
if (!("grid" in demo)) {
    demo.grid = {};
}

/**
 * Build grid.
 */
demo.grid.buildGrid = function(configuration) {
    var params = {
        queryOptions: {
            ignoreCase: true
        },
        rowSelector: "20px",
        noDataMessage: "There are no data retrieved",
        plugins: {
            nestedSorting: true,
            dnd: true,
            indirectSelection: {
                name: "",
                width: "25px",
                styles: "text-align: center;"
            }
        },
        width: "100%"
    };

    dojo.mixin(params, configuration.params);
    dojo.mixin(params.plugins, configuration.plugins);
    
    var node = configuration.node;
    var grid = new dojox.grid.EnhancedGrid(params, node);

    grid.startup();

    dojo.connect(window, "resize", grid, "resize");

    // header cell tooltip
    dojo.connect(grid, "onHeaderCellMouseOver", demo.grid.showTooltip);
    dojo.connect(grid, "onHeaderCellMouseOut", demo.grid.hideTooltip);

    // click cell to select row
    grid.onCellClick = demo.grid.onCellClick;

    // onCellContextMenu, onSelected, onDeselected, onCellClick
    for (var eventHandler in configuration.eventHandlers) {
        grid[eventHandler] = configuration.eventHandlers[eventHandler];
    }

    return grid;
};

demo.grid.onCellClick = function(e) {
    // Overwritten, see dojox.grid._Events.onCellClick()
    if (this.isDndSelectEnable) {
        this.select.drugSelectRow(e.rowIndex);
    } else {
        this.inherited(arguments);
    }
};

demo.grid.showTooltip = function(e) {
    var cell = e.cell;
    dijit.showTooltip(cell.name || "", e.cellNode);
};

demo.grid.hideTooltip = function(e) {
    dijit.hideTooltip(e.cellNode);
    // FIXME: make sure that pesky tooltip doesn't reappear!
    // would be nice if there were a way to hide tooltip without regard to aroundNode.
    dijit._masterTT._onDeck = null;
};

demo.grid.formatMetadata = function(node, metadata) {
    var container = dojo.create("small", null, node);
    var table = dojo.place('<table align="center"><tbody></tbody></table>', container);

    dojo.forEach(metadata, function(item) {
        if (item.name) {
            var tr = dojo.create("tr", null, table);
            var td = dojo.create("td", {
                align: "right",
                innerHTML: item.name
            }, tr);
            dojo.addClass(td, "dojoxLegendText");
            var td2 = dojo.create("td", {
                innerHTML: ":"
            }, tr);
            dojo.addClass(td2, "dojoxLegendText");
            var td3 = dojo.create("td", {
                innerHTML: item.value
            }, tr);
            dojo.addClass(td3, "dojoxLegendText");
        }
    });
};

demo.grid.columnSelectorCheckBoxes = [];

demo.grid.buildColumnSelectorHeaderMenu = function(grid) {
    var menu = new dijit.Menu({
        id: "columnSelectorMenu"
    });

    menu.addChild(new dijit.MenuItem({
        label: "Select columns to display"
    }));
    menu.addChild(new dijit.MenuSeparator());

    var placeholderMenuItem = new dojox.widget.PlaceholderMenuItem({
        label:"GridColumns"
    });
    menu.addChild(placeholderMenuItem);

    grid.attr("headerMenu", menu);
    grid.setupHeaderMenu();

    return menu;
};

demo.grid.buildColumnSelectorContainer = function(grid, containerNode, listSize) {

    /*
     * <div id="container">
     *   <table width="100%" border="1">
     *     <tbody>
     *       <tr class="column-selector-pane">
     *         <td>
     *           <li id="column_selector_item_0">
     *            <input id="column_selector_checkbox_0" />
     *            <label id="column_selector_label_0" for="column_selector_checkbox_0">Column Name 0</label>
     *           </li>
     *           <li id="column_selector_item_1">
     *            <input id="column_selector_checkbox_1" />
     *            <label id="column_selector_label_1" for="column_selector_checkbox_1">Column Name 1</label>
     *           </li>
     *         </td>
     *         <td></td>
     *       </tr>
     *     <tbody>
     *   </table>
     *   <div>
     *     <button id="selectAllButton" onclick="selectAll();">Select all</button>
     *     <button id="clearAllButton" onclick="clearAll();">Clear all</button>
     *   </div>
     * </div>
     */

    var _destroyContainer = function(containerNode) {
        // destroy widgets
        var selectAllButton = dijit.byId("selectAllButton");
        if (selectAllButton) {
            selectAllButton.destroy();
        }

        var clearAllButton = dijit.byId("clearAllButton");
        if (clearAllButton) {
            clearAllButton.destroy();
        }

        // clean up container node
        dojo.empty(containerNode);
    };

    // initalize
    var paneContainer = null;
    if (dojo.query("tr.column-selector-pane", containerNode).length !== 1) {
        // clean up
        _destroyContainer(containerNode);

        // column selector pane container
        var table = dojo.place('<table width="100%" border="1"></table>', containerNode);
        var tbody = dojo.create("tbody", null, table);
        paneContainer = dojo.place('<tr class="column-selector-pane"></tr>', tbody);

        // button container
        var buttonContainer = dojo.create("div", null, containerNode);
        var selectAllButton = new dijit.form.Button({
            id: "selectAllButton",
            label: "Select all",
            onClick: demo.grid.selectAllColumns
        });
        buttonContainer.appendChild(selectAllButton.domNode);

        var clearAllButton = new dijit.form.Button({
            id: "clearAllButton",
            label: "Clear all",
            onClick: demo.grid.deselectAllColumns
        });
        buttonContainer.appendChild(clearAllButton.domNode);
    }

    var listItemIndex = 0;

    var cells = grid.layout.cells;
    dojo.forEach(cells, function(cell) {
        // skip checkbox cell
        if ((cell instanceof dojox.grid.cells.Cell) === false) {
            return;
        }

        // create panes
        var paneIndex = Math.floor(listItemIndex / listSize);
        var paneCount = dojo.query("td", paneContainer).length;
        for (var i = paneCount; i <= paneIndex; i++) {
            dojo.create("td", null, paneContainer);
        }

        // define pane for list
        var pane = null;
        var panes = dojo.query("td", paneContainer);
        if (panes[paneIndex]) {
            pane = panes[paneIndex];
        }

        // create list item
        demo.grid.buildColumnSelectorItem(cell, listItemIndex, pane);

        // increase index
        listItemIndex++;
    });
};

demo.grid.buildColumnSelectorItem = function(cell, itemIndex, paneNode) {
    // item node
    var itemId = "column_selector_item_" + itemIndex;
    var itemNode = dojo.byId(itemId);
    if (!itemNode) {
        itemNode = dojo.create("li", {
            id: itemId
        }, paneNode);
    }

    // checkbox
    var checkboxId = "column_selector_checkbox_" + itemIndex;
    var checkbox = dijit.byId(checkboxId);
    if (!checkbox) {
        var checkboxNode = dojo.create("input", {
            type: "checkbox"
        }, itemNode);
        checkbox = new dijit.form.CheckBox({
            id: checkboxId
        }, checkboxNode);

        // save checkbox widget in a global place
        demo.grid.columnSelectorCheckBoxes.push(checkbox);
    }
    checkbox.attr("name", cell.index);
    checkbox.attr("checked", cell.hidden ? false : true);

    // column name
    var labelId = "column_selector_label_" + itemIndex;
    var labelNode = dojo.byId(labelId);
    if (!labelNode) {
        labelNode = dojo.create("label", {
            id: labelId,
            "for": checkboxId
        }, itemNode);
    }
    labelNode.innerHTML = cell.name;
};

demo.grid.selectAllColumns = function() {
    var checkboxes = demo.grid.columnSelectorCheckBoxes;

    dojo.forEach(checkboxes, function(checkbox) {
        checkbox.attr("checked", true);
    });
};

demo.grid.deselectAllColumns = function() {
    var checkboxes = demo.grid.columnSelectorCheckBoxes;

    dojo.forEach(checkboxes, function(checkbox) {
        checkbox.attr("checked", false);
    });
};

demo.grid.showSelectedColumns = function(grid, callback) {
    var visibleColumns = [];

    var checkboxes = demo.grid.columnSelectorCheckBoxes;
    dojo.forEach(checkboxes, function(checkbox) {
        var cellIndex = checkbox.attr("name");
        if (demo.utils.isNumber(cellIndex)) {
            // set cell hidden attribute
            var cell = grid.getCell(cellIndex);
            cell.hidden = checkbox.attr("checked") ? false : true;

            // update header menu
            dojo.forEach(cell.menuItems, function(menuItem) {
                menuItem.attr("checked", !cell.hidden);
            });

            if (!cell.hidden) {
                visibleColumns.push(cell);
            }
        }
    });

    // update grid
    dojo.forEach(grid.views.views, function(view) {
        view.update();
    });

    if (callback) {
        callback.call(this, visibleColumns);
    }
};

/**
 * 
 * @param {Object} grid
 */
demo.grid.restoreColumns = function(grid) {
    demo.grid._restoreColumnsByResetStructure(grid);
};

/**
 * TODO: DnD for row selection does not work.
 * @param {Object} grid
 */
demo.grid._restoreColumnsByResetStructure = function(grid) {
    grid.select.cancelDND();

    //grid.pluginMgr && grid.pluginMgr.preInit();
    var structure = grid.structure;
    grid.attr("structure", structure);
    grid.pluginMgr && grid.pluginMgr.postInit();
    grid.render();
};

/**
 * TODO: DnD for column selection works wrong.
 * @param {Object} grid
 */
demo.grid._restoreColumnsBySortStructure = function(grid) {
    var _cellComparator = function(cell1, cell2) {
        return cell1.layoutIndex - cell2.layoutIndex;
    };

    grid.select.cancelDND();

    // sort cells in structured array
    dojo.forEach(grid.layout.structure, function(viewStructure) {
        var cells = viewStructure.cells[0];
        if (dojo.isArray(cells)) {
            cells.sort(_cellComparator);
        }
    });

    // sort cells in flat array
    grid.layout.cells.sort(_cellComparator);

    // restroe cell index to initial index
    dojo.forEach(grid.layout.cells, function(cell) {
        cell.index = cell.layoutIndex;
    });

    //grid.setupHeaderMenu();
    grid.render();
};
